package web;

import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.primefaces.model.chart.CartesianChartModel;
import org.primefaces.model.chart.ChartSeries;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import service.ContaService;
import service.FaturaService;
import service.ParcelaTransacaoService;
import util.UtilColecao;
import util.UtilData;
import util.UtilMensagem;
import entity.Conta;
import entity.ContaCredito;
import entity.Fatura;
import entity.ParcelaTransacao;
import enumeration.TipoContaEnum;

@Controller
@Scope("view")
public class FaturaMB extends BaseManagedBean implements Serializable {

    private static final long serialVersionUID = 7863504781978243773L;

    @Autowired
    private FaturaService faturaService;

    @Autowired
    private ParcelaTransacaoService parcelaTransacaoService;

    @Autowired
    private ContaService contaService;

    private List<ContaCredito> listaContasCredito;

    private List<ParcelaTransacao> listaParcelarPorFatura;

    private List<Date> listaMeses;

    private Map<Date, BigDecimal> valorTodasFaturasPorMes;

    private CartesianChartModel graficoCartoesModel;

    private Fatura faturaFechamento;

    private List<Conta> listaContasPagamentoFatura;

    private Integer anoFaturas;

    @Override
    public void inicializar() {

	listaContasCredito = contaService.listarCartoesCreditoComFaturas();

	anoFaturas = Calendar.getInstance().get(Calendar.YEAR);

	doCarregarFaturas();
    }

    public void doCarregarFaturas() {
	valorTodasFaturasPorMes = new HashMap<Date, BigDecimal>();
	listaMeses = new ArrayList<Date>();
	for (int i = 1; i < 13; i++) {
	    final Date mes = UtilData.getCalendar(i, anoFaturas).getTime();
	    listaMeses.add(mes);

	    for (ContaCredito cartao : listaContasCredito) {
		final Fatura fatura = cartao.buscarFaturaPorDate(mes);

		if (fatura != null) {
		    for (ParcelaTransacao parc : fatura.getListaParcelas()) {
			fatura.setValorTotal(fatura.getValorTotal().add(
				parc.getValor()));
		    }

		    BigDecimal valorPorMes = valorTodasFaturasPorMes.get(mes);
		    if (valorPorMes == null) {
			valorTodasFaturasPorMes
				.put(mes, fatura.getValorTotal());
		    } else {
			valorTodasFaturasPorMes.put(mes,
				valorPorMes.add(fatura.getValorTotal()));
		    }
		}
	    }
	}

	criarGraficoCartoesModel();
    }

    private void criarGraficoCartoesModel() {
	graficoCartoesModel = new CartesianChartModel();
	SimpleDateFormat sdfMes = new SimpleDateFormat("MMMMM");

	for (ContaCredito cartao : listaContasCredito) {

	    ChartSeries cartaoGraf = new ChartSeries();
	    cartaoGraf.setLabel(cartao.getNome());

	    for (Date mes : listaMeses) {
		final Fatura fatura = buscarFatura(cartao, mes);

		if (fatura != null) {
		    cartaoGraf.set(sdfMes.format(mes), fatura.getValorTotal());

		} else {
		    cartaoGraf.set(sdfMes.format(mes), 0);
		}
	    }

	    graficoCartoesModel.addSeries(cartaoGraf);
	}
    }

    public void alterarParcela(ParcelaTransacao parcelaTransacao) {
	parcelaTransacaoService.salvar(parcelaTransacao);
	parcelaTransacao.setEditando(false);
	inicializar();
    }

    public void carregarParcelasPorFatura(ContaCredito ContaCredito, Date mes) {
	final Fatura fatura = buscarFatura(ContaCredito, mes);
	listaParcelarPorFatura = new ArrayList<ParcelaTransacao>(
		fatura.getListaParcelas());
    }

    public void carregarModalFecharFatura(ContaCredito contaCredito, Date mes) {
	faturaFechamento = buscarFatura(contaCredito, mes);

	final Calendar dataFechamento = Calendar.getInstance();
	dataFechamento.setTime(mes);
	dataFechamento.set(Calendar.DAY_OF_MONTH,
		contaCredito.getDiaFechamentoFatura());
	
	final Calendar dataVencimento = Calendar.getInstance();
	dataVencimento.setTime(mes);
	dataVencimento.add(Calendar.MONTH, 1);
	dataVencimento.set(Calendar.DAY_OF_MONTH,
		contaCredito.getDiaVencimentoFatura());

	faturaFechamento.setDataFechamento(dataFechamento.getTime());
	faturaFechamento.setDataVencimento(dataVencimento.getTime());

	listaContasPagamentoFatura = contaService.listarAtivos();

	if (!UtilColecao.isColecaoVazia(listaContasPagamentoFatura)) {
	    for (Conta conta : listaContasPagamentoFatura) {
		if (conta.equals(contaCredito)) {
		    listaContasPagamentoFatura.remove(conta);
		    break;
		}
	    }

	    for (Conta conta : listaContasPagamentoFatura) {
		if (conta.getTipoConta().equals(TipoContaEnum.BANCARIA)) {
		    faturaFechamento.setContaPagamento(conta);
		    break;
		}
	    }
	}
    }

    public Fatura buscarFatura(ContaCredito ContaCredito, Date mes) {
	for (ContaCredito cartao : listaContasCredito) {
	    if (cartao.equals(ContaCredito)) {
		return cartao.buscarFaturaPorDate(mes);
	    }
	}

	return null;
    }

    public void fecharFatura() {

	faturaService.fecharFatura(faturaFechamento);

	addInfoMessage(UtilMensagem.getMensagem("MSG_0043"));
    }

    public boolean isMesAtual(Date mes) {

	final Calendar dataAtual = UtilData.getCalendar(new Date());
	final int mesAtual = dataAtual.get(Calendar.MONTH);
	final int anoAtual = dataAtual.get(Calendar.YEAR);

	final Calendar dataVerificar = UtilData.getCalendar(mes);
	final int mesVerificar = dataVerificar.get(Calendar.MONTH);
	final int anoVerificar = dataVerificar.get(Calendar.YEAR);

	return mesAtual == mesVerificar && anoAtual == anoVerificar;
    }

    public BigDecimal buscarSomaTotalPorMes(Date mes) {
	return valorTodasFaturasPorMes.get(mes);
    }

    public List<Date> getListaMeses() {
	return listaMeses;
    }

    public void setListaMeses(List<Date> listaMeses) {
	this.listaMeses = listaMeses;
    }

    public CartesianChartModel getGraficoCartoesModel() {
	return graficoCartoesModel;
    }

    public List<ParcelaTransacao> getListaParcelarPorFatura() {
	return listaParcelarPorFatura;
    }

    public Fatura getFaturaFechamento() {
	return faturaFechamento;
    }

    public void setFaturaFechamento(Fatura faturaFechamento) {
	this.faturaFechamento = faturaFechamento;
    }

    public List<Conta> getListaContasPagamentoFatura() {
	return listaContasPagamentoFatura;
    }

    public void setListaContasPagamentoFatura(
	    List<Conta> listaContasPagamentoFatura) {
	this.listaContasPagamentoFatura = listaContasPagamentoFatura;
    }

    public Integer getAnoFaturas() {
	return anoFaturas;
    }

    public void setAnoFaturas(Integer anoFaturas) {
	this.anoFaturas = anoFaturas;
    }

    public List<ContaCredito> getListaContasCredito() {
	return listaContasCredito;
    }

    public void setListaContasCredito(List<ContaCredito> listaContasCredito) {
	this.listaContasCredito = listaContasCredito;
    }

}
